package com.api.model;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.time.Instant;
/**
 * @Classname NtpClient
 * @Description TODO
 * @Date 2023/10/26 11:08
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class NtpClient {


    private static final int NTP_PORT = 123;
    private static final int NTP_PACKET_SIZE = 48;
    private static final long NTP_TO_UNIX_EPOCH = 2208988800L;

    public static void main(String[] args) {
        String ntpServerAddress = "192.168.1.100"; // 替换为实际的NTP服务器地址

        try (DatagramSocket socket = new DatagramSocket()) {
            InetAddress serverAddress = InetAddress.getByName(ntpServerAddress);

            byte[] requestPacket = createNtpRequestPacket();
            DatagramPacket requestPacket1 = new DatagramPacket(requestPacket, requestPacket.length, serverAddress, NTP_PORT);
            socket.send(requestPacket1);

            byte[] responsePacket3 = new byte[NTP_PACKET_SIZE];
            DatagramPacket responsePacket2 = new DatagramPacket(responsePacket3, responsePacket3.length);
            socket.receive(responsePacket2);

            long ntpTime = readNtpTime(responsePacket3);
            long currentTimeMillis = System.currentTimeMillis();
            long offsetInMillis = (ntpTime - currentTimeMillis) / 2;

            System.out.println("NTP server time: " + Instant.ofEpochMilli(ntpTime));
            System.out.println("System time: " + Instant.ofEpochMilli(currentTimeMillis));
            System.out.println("Time offset: " + offsetInMillis + " milliseconds");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static byte[] createNtpRequestPacket() {
        byte[] packet = new byte[NTP_PACKET_SIZE];
        packet[0] = 0x1B; // Leap Indicator, Version, Mode
        return packet;
    }

    private static long readNtpTime(byte[] packet) {
        long seconds = read32BitLong(packet, 40);
        long fraction = read32BitLong(packet, 44);
        return (seconds - NTP_TO_UNIX_EPOCH) * 1000 + fraction * 1000L / 0x100000000L;
    }

    private static long read32BitLong(byte[] packet, int offset) {
        long value = 0;
        for (int i = 0; i < 4; i++) {
            value = (value << 8) | (packet[offset + i] & 0xFF);
        }
        return value;
    }
}
